//
//  AjenObject.m
//  AjenKit
//
//  Created by Ajen on 2017/8/31.
//  Copyright © 2017年 中国·北京·洵. All rights reserved.
//
//
//                       .::::.
//                     .::::::::.
//                    ::::Ajen:::
//                 ..:::::::::::'
//              '::::::::::::'
//                .::::::::::
//           '::::::::::::::..
//                 .::::::::::::.
//                ::::::::::::::::
//               ::::``:::::::::'        .:::.
//              ::::'   ':::::'       .::::::::.
//            .::::'      ::::     .:::::::'::::.
//           .:::'       :::::  .:::::::::' ':::::.
//          .::'        :::::.:::::::::'      ':::::.
//         .::'         ::::::::::::::'         ``::::.
//     ...:::           ::::::::::::'              ``::.
//    ````              ':::::::::'                  ::::..
//                       '.:::::'                    ':'````..
//  [······Object拓展······]
//

#import "AjenObject.h"
#import <CoreData/CoreData.h>
#import <objc/runtime.h>
@implementation AjenObject
+(NSManagedObjectContext *)getCoreDataContextWithDBName:(NSString *)dbName{
    //1、创建模型对象
    //获取模型路径
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:dbName withExtension:@"momd"];
    //根据模型文件创建模型对象
    NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    //2、创建持久化存储助理：数据库
    //利用模型对象创建助理对象
    NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    //数据库的名称和路径
    NSString *docStr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *sqlPath = [docStr stringByAppendingPathComponent:@"coreData.sqlite"];
    NSLog(@"数据库 path = %@", sqlPath);
    NSURL *sqlUrl = [NSURL fileURLWithPath:sqlPath];
    NSError *error = nil;
    //设置数据库相关信息 添加一个持久化存储库并设置类型和路径，NSSQLiteStoreType：SQLite作为存储库
    [store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:sqlUrl options:nil error:&error];
    if (error) {
        NSLog(@"添加数据库失败:%@",error);
    } else {
        NSLog(@"添加数据库成功");
    }
    //3、创建上下文 保存信息 对数据库进行操作
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    //关联持久化助理
    context.persistentStoreCoordinator = store;
    return context;
}
@end


#ifdef DEBUG
static inline void sq_swizzleSelector(Class class, SEL originalSelector, SEL swizzledSelector) {
    
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    
    BOOL didAddMethod = class_addMethod(class,
                                        originalSelector,
                                        method_getImplementation(swizzledMethod),
                                        method_getTypeEncoding(swizzledMethod));
    if (didAddMethod) {
        class_replaceMethod(class,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}
#endif


@implementation NSObject (AjenObject)

-(BOOL)aj_isNull{
    if([self isEqual:[NSNull null]] || [self isEqual:NULL] || [self isEqual:nil] || [self isEqual:Nil]|| self == nil || self == NULL || self == Nil || [self isKindOfClass:[NSNull class]] || [[self class] isSubclassOfClass:[NSNull class]] || [self isKindOfClass:[NSNull class]] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"(null)"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"<null>"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"NULL"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"null"]){
        return YES;
    }else{
        return NO;
    }
}


-(NSString *)aj_changeToString{
    return (NSString *)self;
}

-(NSString *)aj_changeToJson{
    NSError *parseError = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:&parseError];
    NSString * jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    return jsonString;
}

- (NSString *(^)(id obj)) aj_toString{
    return ^id(id obj){
        return [NSString stringWithFormat:@"%@",obj];
    };
}

//将obj转换成json字符串。如果失败则返回nil.
- (NSString *)convertToJsonString {
    
    //先判断是否能转化为JSON格式
    if (![NSJSONSerialization isValidJSONObject:self])  return nil;
    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted  error:&error];
    if (error || !jsonData) return nil;
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    return jsonString;
}

-(NSArray *)getAllPropertyName{
    u_int count = 0;
    //传递count的地址
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    NSMutableArray *propertyArray = [NSMutableArray arrayWithCapacity:count];
    for (int i = 0; i < count; i++) {
        //得到的propertyName为C语言的字符串
        const char *propertyName = property_getName(properties[i]);
        [propertyArray addObject:[NSString stringWithUTF8String:propertyName]];
    }
    free(properties);
    return propertyArray;
}

@end


@implementation NSString (AjenString)

-(BOOL)aj_isEmpty{
    if ([self isEqual:@"NULL"] || [self isKindOfClass:[NSNull class]] || [self isEqual:[NSNull null]] || [self isEqual:NULL] || [[self class] isSubclassOfClass:[NSNull class]] || self == nil || self == NULL || [self isKindOfClass:[NSNull class]] || [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]==0 || [self isEqualToString:@"<null>"] || [self isEqualToString:@"(null)"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"(null)"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"<null>"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"NULL"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"null"]){
        return YES;
    }else{
        return NO;
    }
}

-(BOOL)isEmptyString{
    if ([self isEqual:@"NULL"] || [self isKindOfClass:[NSNull class]] || [self isEqual:[NSNull null]] || [self isEqual:NULL] || [[self class] isSubclassOfClass:[NSNull class]] || self == nil || self == NULL || [self isKindOfClass:[NSNull class]] || [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]==0 || [self isEqualToString:@"<null>"] || [self isEqualToString:@"(null)"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"(null)"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"<null>"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"NULL"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"null"]){
        return YES;
    }else{
        return NO;
    }
}

-(NSString *)aj_formatEmpty{
    if ([self isEqual:@"NULL"] || [self isKindOfClass:[NSNull class]] || [self isEqual:[NSNull null]] || [self isEqual:NULL] || [[self class] isSubclassOfClass:[NSNull class]] || self == nil || self == NULL || [self isKindOfClass:[NSNull class]] || [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]==0 || [self isEqualToString:@"<null>"] || [self isEqualToString:@"(null)"]|| [[NSString stringWithFormat:@"%@",self] isEqualToString:@"(null)"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"<null>"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"NULL"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"null"]){
        return @"";
    }else{
        return self;
    }
}
-(NSString*)formatEmptyString{
    if ([self isEqual:@"NULL"] || [self isKindOfClass:[NSNull class]] || [self isEqual:[NSNull null]] || [self isEqual:NULL] || [[self class] isSubclassOfClass:[NSNull class]] || self == nil || self == NULL || [self isKindOfClass:[NSNull class]] || [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]==0 || [self isEqualToString:@"<null>"] || [self isEqualToString:@"(null)"]|| [[NSString stringWithFormat:@"%@",self] isEqualToString:@"(null)"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"<null>"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"NULL"] || [[NSString stringWithFormat:@"%@",self] isEqualToString:@"null"]){
        return @"";
    }else{
        return self;
    }
}

+(NSString *)stringWithFloat:(float)f{
    if (fmodf(f, 1)==0) {//如果有一位小数点
        return [NSString stringWithFormat:@"%.0f",f];
    } else if (fmodf(f*10, 1)==0) {//如果有两位小数点
        return [NSString stringWithFormat:@"%.1f",f];
    } else {
        return [NSString stringWithFormat:@"%.2f",f];
    }
}

+(NSString*)formatFloat:(float)f{
    if (fmodf(f, 1)==0) {//如果有一位小数点
        return [NSString stringWithFormat:@"%.0f",f];
    } else if (fmodf(f*10, 1)==0) {//如果有两位小数点
        return [NSString stringWithFormat:@"%.1f",f];
    } else {
        return [NSString stringWithFormat:@"%.2f",f];
    }
}
@end

@implementation NSArray (AjenArray)
-(NSArray *)AJInster:(NSInteger)index Obj:(id)obj{
    NSMutableArray * mu = [self mutableCopy];
    [mu insertObject:obj atIndex:index];
    return mu;
}
- (NSArray *(^)(NSInteger index,id Obj)) aj_insert{
    return ^id(NSInteger index,id Obj){
        NSMutableArray * mu = [self mutableCopy];
        [mu insertObject:Obj atIndex:index];
        return mu;
    };
}

- (NSArray *(^)(NSInteger index_plaintiff,NSInteger index_accused)) aj_exchangeIndex{
    return ^id(NSInteger index_plaintiff,NSInteger index_accused){
        NSMutableArray * mu = [self mutableCopy];
        [mu exchangeObjectAtIndex:index_plaintiff withObjectAtIndex:index_accused];
        return mu;
    };
}

- (NSArray *)AJExchangeIndex:(NSInteger)index_plaintiff with:(NSInteger)index_accused{
    NSMutableArray * mu = [self mutableCopy];
    [mu exchangeObjectAtIndex:index_plaintiff withObjectAtIndex:index_accused];
    return mu;
}


- (NSArray *(^)(NSInteger index_start,NSInteger index_to)) aj_jumpToIndex{
    return ^id(NSInteger index_start,NSInteger index_to){
        NSMutableArray * mu = [self mutableCopy];
        id temp = mu[index_start];
        [mu removeObjectAtIndex:index_start];
        [mu insertObject:temp atIndex:index_to];
        return mu;
    };
}
- (NSArray *)AJJumpToIndex:(NSInteger)index_start with:(NSInteger)index_to{
    NSMutableArray * mu = [self mutableCopy];
    id temp = mu[index_start];
    [mu removeObjectAtIndex:index_start];
    [mu insertObject:temp atIndex:index_to];
    return mu;
}


- (NSArray *(^)(NSInteger index)) aj_removeIndex{
    return ^id(NSInteger index){
        NSMutableArray * mu = [self mutableCopy];
        [mu removeObjectAtIndex:index];
        return mu;
    };
}
- (NSArray *)AJRemoveIndex:(NSInteger)index{
    NSMutableArray * mu = [self mutableCopy];
    [mu removeObjectAtIndex:index];
    return mu;
}



- (NSArray *(^)(NSArray * indexs)) aj_removeIndexs{
    return ^id(NSArray * indexs){
        NSMutableArray * mu = [self mutableCopy];
        for(int i = 0 ; i < indexs.count ; i++){
            [mu removeObjectAtIndex:i];
        }
        return mu;
    };
}
- (NSArray *)AJRemoveIndexs:(NSArray *)indexs{
    NSMutableArray * mu = [self mutableCopy];
    for(int i = 0 ; i < indexs.count ; i++){
        [mu removeObjectAtIndex:i];
    }
    return mu;
}

#ifdef DEBUG
//用此方法交换系统的 descriptionWithLocale: 方法。该方法在代码打印的时候调用。
- (NSString *)sqjsonlog_descriptionWithLocale:(id)locale{
    
    NSString *result = [self convertToJsonString];
    if (!result) return [self sqjsonlog_descriptionWithLocale:locale];
    return result;
}
//用此方法交换系统的 descriptionWithLocale:indent:方法。功能同上。
- (NSString *)sqjsonlog_descriptionWithLocale:(id)locale indent:(NSUInteger)level {
    
    NSString *result = [self convertToJsonString];
    if (!result) return [self sqjsonlog_descriptionWithLocale:locale indent:level];
    return result;
}
//用此方法交换系统的 debugDescription 方法。该方法在控制台使用po打印的时候调用。
- (NSString *)sqjsonlog_debugDescription{
    
    NSString *result = [self convertToJsonString];
    if (!result) return [self sqjsonlog_debugDescription];
    return result;
}

+ (void)load {
    
    //方法交换
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        Class class = [self class];
        sq_swizzleSelector(class, @selector(descriptionWithLocale:), @selector(sqjsonlog_descriptionWithLocale:));
        sq_swizzleSelector(class, @selector(descriptionWithLocale:indent:), @selector(sqjsonlog_descriptionWithLocale:indent:));
        sq_swizzleSelector(class, @selector(debugDescription), @selector(sqjsonlog_debugDescription));
    });
}
#endif


@end



@implementation NSDictionary (SQJsonLog)

#ifdef DEBUG
//用此方法交换系统的 descriptionWithLocale: 方法。该方法在代码打印的时候调用。
- (NSString *)sqjsonlog_descriptionWithLocale:(id)locale{
    
    NSString *result = [self convertToJsonString];//转换成JSON格式字符串
    if (!result) return [self sqjsonlog_descriptionWithLocale:locale];//如果无法转换，就使用原先的格式
    return result;
}
//用此方法交换系统的 descriptionWithLocale:indent:方法。功能同上。
- (NSString *)sqjsonlog_descriptionWithLocale:(id)locale indent:(NSUInteger)level {
    
    NSString *result = [self convertToJsonString];
    if (!result) return [self sqjsonlog_descriptionWithLocale:locale indent:level];
    return result;
}
//用此方法交换系统的 debugDescription 方法。该方法在控制台使用po打印的时候调用。
- (NSString *)sqjsonlog_debugDescription{
    
    NSString *result = [self convertToJsonString];
    if (!result) return [self sqjsonlog_debugDescription];
    return result;
}

//在load方法中完成方法交换
+ (void)load {
    
    //方法交换
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        sq_swizzleSelector(class, @selector(descriptionWithLocale:), @selector(sqjsonlog_descriptionWithLocale:));
        sq_swizzleSelector(class, @selector(descriptionWithLocale:indent:), @selector(sqjsonlog_descriptionWithLocale:indent:));
        sq_swizzleSelector(class, @selector(debugDescription), @selector(sqjsonlog_debugDescription));
    });
}
#endif
@end














